//
//  JKStatusListModel.swift
//  JKWeibo
//
//  Created by albert on 16/6/23.
//  Copyright © 2016年 albert. All rights reserved.
//  加载微博数据

import UIKit
import SDWebImage

class JKStatusListModel: NSObject {
    /** 保存所有的微博数据 */
    var statuses: [JKStatusViewModel]?
    
    /** loadNewData */
    func loadNewData(lastCellFlag: Bool, finished: (models: [JKStatusViewModel]?, error: NSError?) -> ()) {
        
        // 1.获取用户uid
        guard let userID = JKUserAccount.loadUserAccount()?.uid else {
            JKLog("用户没有登录")
            return
        }
        
        // 2.获取since_id和max_id
        var since_id = "0"
        var max_id = "0"
        
        // 如果是最后一条微博
        if lastCellFlag {
            since_id = "0"
            max_id = statuses?.last?.status.idstr ?? "0"
            
        }else { // 不是最后一条
            since_id = statuses?.first?.status.idstr ?? "0"
            max_id = "0"
        }
        
        // 3.拼接查询的SQL
        var querySQL = "SELECT * FROM t_status WHERE userID = \(userID)"
        if since_id != "0" {
            querySQL += " AND statusID > \(since_id)"
            
        }else if max_id != "0" {
            let temp = Int(max_id)! - 1
            querySQL += " AND statusID <= \(temp)"
        }
        
        querySQL += " ORDER BY statusID DESC LIMIT 20;"
        
        // 4.执行查询的SQL语句
        SQLiteManager.sharedInstance.dbQueue?.inDatabase({ (db) -> Void in
            // 4.1获取查询结果
            let result = db.executeQuery(querySQL, withArgumentsInArray: nil)
            
            // 4.2遍历所有的查询结果
            var models = [JKStatusViewModel]()
            while result.next() {
                // 4.2.1获取微博的字符串
                let statusText = result.stringForColumn("statusText")
                
                // 4.2.2将字符串转为字典
                guard let data = statusText.dataUsingEncoding(NSUTF8StringEncoding) else {
                    continue
                }
                guard let dict = try? NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.MutableContainers) else {
                    JKLog("没有获取到微博数据")
                    continue
                }
                
                models.append(JKStatusViewModel(status: JKStatusModel(dict: dict as! [String : AnyObject])))
            }
            
            // 4.3判断数组中是否有值
            if models.count != 0 {
                JKLog("从本地读取数据")
                
                // 4.3.1将获取到的数据拼接到原来的数组中
                if since_id != "0" {
                    // 将新的数据拼接到旧数据前面
                    self.statuses = models + self.statuses!
                    
                }else if max_id != "0" {
                    // 将新的数据拼接到旧数据后面
                    self.statuses = self.statuses! + models
                }else {
                    self.statuses = models
                }
                
                // 4.3.2回调告诉外界现在获取到了数据
                finished(models: models, error: nil)
                
                return
            }
            
            // 5.如果没有从本地读取到数据，那么就从网络中加载数据
            self.loadDataFromNetwork(lastCellFlag, finished: finished)
        })
    }
    
    /** 从网络获取数据 */
    private func loadDataFromNetwork(lastCellFlag: Bool, finished: (models: [JKStatusViewModel]?, error: NSError?) -> ()) {
        /*
        since_id false int64 若指定此参数，则返回ID比since_id大的微博（即比since_id时间晚的微博），默认为0。
        max_id false int64 若指定此参数，则返回ID小于或等于max_id的微博，默认为0。
        默认情况下，新浪返回的数据是按照微博ID从大到校返回给我们的
        这也就意味着微博ID越大，这条微博发布的就越晚
        经过分析，如果要实现下拉刷新数据，指定since_id为第一个微博的id即可
        如果要实现上拉加载更多，需要指定max_id为最后一条微博 id - 1，因为新浪返回的数据包括max_id这条微博
        */
        JKLog("从网络获取数据")
        // 获取since_id和max_id
        var since_id = "0"
        var max_id = "0"
        
        // 如果是最后一条微博
        if lastCellFlag {
            since_id = "0"
            max_id = statuses?.last?.status.idstr ?? "0"
            
        }else { // 不是最后一条
            since_id = statuses?.first?.status.idstr ?? "0"
            max_id = "0"
        }
        
        // 请求微博数据
        JKNetworkingTool.sharedInstance.loadStatuses(since_id, max_id: max_id) { (array, error) -> () in
            
            // 1.安全校验
            if error != nil {
                finished(models: nil, error: error)
                return
            }
            
            guard let arr = array else {
                return
            }
            
            // 2.将字典数据转换为模型数组
            var models = [JKStatusViewModel]()
            for dict in arr {
                let status = JKStatusModel(dict: dict)
                let viewModel = JKStatusViewModel(status: status)
                models.append(viewModel)
            }
            
            // 3.处理微博数据
            if since_id != "0" {
                self.statuses = models + self.statuses!
                
            }else if max_id != "0" {
                self.statuses = self.statuses! + models
                
            }else {
                self.statuses = models
            }
            
            // 4.缓存微博所有配图
            self.cacheImages(models, finished: finished)
            
            // 5.本地缓存数据
            self.cacheData(arr)
        }
    }
    
    /** 缓存微博到本地 */
    private func cacheData(list: [[String : AnyObject]]) {
        // 1.拿到用户的uid
        guard let userID = JKUserAccount.loadUserAccount()?.uid else {
            JKLog("用户ID没有值，即未登录")
            return
        }
        
        // 2.遍历字典数据，拿到每一条微博数据
        for dict in list {
            // 2.1获取微博的ID
            guard let statusID = dict["idstr"] else {
                JKLog("微博ID没有值")
                continue
            }
            
            // 2.2获取微博的内容
            // 2.2.1将字典转为NSData
            guard let data = try? NSJSONSerialization.dataWithJSONObject(dict, options: NSJSONWritingOptions.PrettyPrinted) else {
                JKLog("字典转NSData失败")
                continue
            }
            
            // 2.2.2将NSData转为字符串
            guard let statusText = String(data: data, encoding: NSUTF8StringEncoding) else {
                JKLog("NSData转字符串失败")
                continue
            }
            
            // 3.拼接插入SQL语句
            let insertSQL = "INSERT INTO t_status (statusID, statusText, userID) VALUES (?, ?, ?);"
            
            // 4.执行SQL语句
            SQLiteManager.sharedInstance.dbQueue?.inDatabase({ (db) -> Void in
                db.executeUpdate(insertSQL, withArgumentsInArray: [statusID, statusText, userID])
            })
        }
    }

    /** 缓存所有配图 */
    private func cacheImages(viewModels: [JKStatusViewModel], finished: (models: [JKStatusViewModel]?, error: NSError?) -> ()) {
        // 0.创建一个组
        let group = dispatch_group_create()
        
        for viewModel in viewModels {
            // 1.从模型中取出配图数组
            guard let picUrls = viewModel.thumbnail_pic_urls else {
                // 如果当前微博没有配图就跳过，继续下一个模型的
                continue
            }
            // 2.遍历配图数组下载图片
            for url in picUrls {
                // 将当前的下载操作添加到组中
                dispatch_group_enter(group)
                
                // 3.利用SDWebImage下载图片
                SDWebImageManager.sharedManager().downloadImageWithURL(url, options: SDWebImageOptions(rawValue: 0), progress: nil, completed: { (image, error, _, _, _) -> Void in
                    
                    // 将当前操作从组中移除
                    dispatch_group_leave(group)
                })
            }
        }
        
        // 监听下载操作
        dispatch_group_notify(group, dispatch_get_main_queue()) { () -> Void in
            // 因为已经赋值过了，所以这里直接刷新表格
            finished(models: viewModels, error: nil)
        }
    }
    
    /** 清理缓存的数据 */
    class func clearData() {
        // 1.获取三天前的时间
        let threeDaysAgoDate = NSDate(timeIntervalSinceNow: -3 * 24 * 60 * 60)
        let fmt = NSDateFormatter()
        fmt.dateFormat = "yyyy-MM-dd HH:mm:ss" // 2016-07-02 17:25:11
        let dateString = fmt.stringFromDate(threeDaysAgoDate)
        
        // 2.拼接删除数据的SQL
        let deleteSQL = "DELETE FROM t_status WHERE createTime < '\(dateString)';"
        
        // 3.执行SQL语句
        SQLiteManager.sharedInstance.dbQueue?.inDatabase({ (db) -> Void in
            db.executeUpdate(deleteSQL, withArgumentsInArray: nil)
        })
    }
}
